package com.jt.www.admin.order_pc.controller;

import com.google.common.base.Function;
import com.google.common.collect.Lists;
import com.jt.www.admin.order_pc.service.ExportConfigService;
import com.jt.www.admin.order_pc.service.OfflineEndorseService;
import com.jt.www.admin.user.service.UserService;
import com.jt.www.annotations.AvoidRepeatableCommit;
import com.jt.www.domain.bo.OfflineEndorseBO;
import com.jt.www.domain.dto.OfflineEndorseOutputDTO;
import com.jt.www.domain.enums.common.ExportChannelTypeEnum;
import com.jt.www.domain.po.ExportConfigEntity;
import com.jt.www.domain.po.OfflineEndorse;
import com.jt.www.domain.qo.OfflineEndorseQO;
import com.jt.www.domain.vo.OfflineEndorsePolicyVo;
import com.jt.www.model.reps.GenericDataResponse;
import com.jt.www.model.reps.GenericListResponse;
import com.jt.www.util.RedisUtil;
import com.jt.www.util.excel.CsvExportUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Date;
import java.util.List;

/**
 * 线下批单录入业务
 * Created by shaoyn on 2020/05/22.
 */
@Api(value = "线下批单录入", tags = {"OFFLINE-ENDORSE-API"}, description = "线下批单录入")
@RestController
@RequestMapping(value = "/offline/endorse")
public class OfflineEndorseController {

    public static final Logger log = LoggerFactory.getLogger(OfflineEndorseController.class);
    private static final String JTPF_USER_ID = "jtpf.userId";
    private static final String AUDIT_OFFLINE_ENDORSE = "AUDIT_OFFLINE_ENDORSE_";
    @Autowired
    private OfflineEndorseService offlineEndorseService;
    @Autowired
    private ExportConfigService exportConfigService;
    @Autowired
    private UserService userService;

    /**
     * 批单录入
     *
     * @return
     */
    @ApiOperation(value = "批单录入", notes = "批单录入", httpMethod = "POST")
    @PostMapping(value = "/saveOfflineEndorse", produces = {MediaType.APPLICATION_JSON_UTF8_VALUE})
    @AvoidRepeatableCommit
    public ResponseEntity saveOfflineEndorse(@RequestBody OfflineEndorse offlineEndorse) {
        //如果产品信息为空或 产品编码为空 返回报错信息
        if (null == offlineEndorse.getPolicyNo()) {
            return GenericDataResponse.errorWithMsg("保单不能为空!");
        }
        if (null == offlineEndorse.getProductCode()) {
            return GenericDataResponse.errorWithMsg("保单产品不能为空!");
        }
        if (null == offlineEndorse.getEndorseNo()) {
            return GenericDataResponse.errorWithMsg("批单号不能为空!");
        }
        if (null == offlineEndorse.getEndorseType()) {
            return GenericDataResponse.errorWithMsg("批单类型不能为空!");
        }
        if (null == offlineEndorse.getInsureDate()) {
            return GenericDataResponse.errorWithMsg("出单时间不能为空!");
        }
        if (null == offlineEndorse.getPremium()) {
            return GenericDataResponse.errorWithMsg("批单保费不能为空!");
        }
        if (null == offlineEndorse.getStartDate()) {
            return GenericDataResponse.errorWithMsg("批单起期不能为空!");
        }
        if (null == offlineEndorse.getEndDate()) {
            return GenericDataResponse.errorWithMsg("批单止期不能为空!");
        }
        if (StringUtils.isBlank(offlineEndorse.getProductCode())) {
            return GenericDataResponse.errorWithMsg("产品不能为空!");
        }

        //前端输入的参数带空格，在这里去掉。
        offlineEndorse.setPolicyNo(offlineEndorse.getPolicyNo().trim());

        String findCode = "SaveOfflineEndorse_" + System.currentTimeMillis();
        if (offlineEndorseService.isExistent(findCode, offlineEndorse.getEndorseNo())) {
            return GenericDataResponse.errorWithMsg("该批单号，已经存在，不能重复录入!");
        }

        int n = offlineEndorseService.saveOfflineEndorse(offlineEndorse);
        if (n > 0) {
            return GenericDataResponse.ok();
        }
        return GenericDataResponse.errorWithMsg("保存失败!");
    }

    @ApiOperation(value = "查询批单号是否存在", notes = "查询批单号是否存在", httpMethod = "GET")
    @GetMapping(value = "/isExistent/{endorseNo}", produces = {MediaType.APPLICATION_JSON_UTF8_VALUE})
    public ResponseEntity<GenericDataResponse<Boolean>> isExistent(@ApiParam(value = "批单号", required = true) @PathVariable String endorseNo) {
        String findCode = "IsExistent_" + System.currentTimeMillis();
        return GenericDataResponse.okWithData(offlineEndorseService.isExistent(findCode, endorseNo));
    }

    @ApiOperation(value = "查询批单出单日期是否跨期", notes = "查询批单出单日期是否跨期", httpMethod = "GET")
    @GetMapping(value = "/isIntertemporal/{endorseNo}", produces = {MediaType.APPLICATION_JSON_UTF8_VALUE})
    public ResponseEntity<GenericDataResponse<Boolean>> isIntertemporal(@ApiParam(value = "批单号", required = true) @PathVariable String endorseNo, @ApiParam(value = "批单出单日期", required = true)
                                                                        @RequestParam Date endorseIssueDate)throws Exception {
        String findCode = "isIntertemporal" + System.currentTimeMillis();
        return GenericDataResponse.okWithData(offlineEndorseService.isIntertemporal(findCode,endorseNo, endorseIssueDate));
    }

    /**
     * 查询批单录入列表
     *
     * @return
     */
    @ApiOperation(value = "查询批单录入列表", notes = "查询批单录入列表", httpMethod = "POST")
    @PostMapping(value = "/queryOfflineEndorse", produces = {MediaType.APPLICATION_JSON_UTF8_VALUE})
    public ResponseEntity<GenericListResponse<OfflineEndorse>> queryOfflineEndorse(@RequestBody OfflineEndorseQO offlineEndorseQO, HttpServletRequest request) {
        String findCode = "queryOfflineEndorse_" + System.currentTimeMillis();
        String userCode = request.getHeader(JTPF_USER_ID);
        String branchCodes = userService.getBranchCodes(findCode, userCode);
        offlineEndorseQO.setOperatorBranchCode(branchCodes);
        if (StringUtils.isBlank(userCode)) {
            log.info("{} 无用户信息!", findCode);
            return GenericListResponse.listNoCount(null);
        }
        return offlineEndorseService.queryOfflineEndorse(offlineEndorseQO);
    }

    /**
     * 查询批单录入详情
     *
     * @return
     */
    @ApiOperation(value = "查询批单录入详情", notes = "查询批单录入详情", httpMethod = "POST")
    @PostMapping(value = "/queryOfflineEndorseDetails/{endorseId}", produces = {MediaType.APPLICATION_JSON_UTF8_VALUE})
    public ResponseEntity<GenericDataResponse<OfflineEndorseBO>> queryCommissionDetails(@ApiParam(value = "线下录单定单ID", required = true) @PathVariable Long endorseId) {
        return offlineEndorseService.queryOfflineEndorseDetails(endorseId);
    }

    /**
     * 修改批单录入
     *
     * @return
     */
    @ApiOperation(value = "修改批单录入", notes = "修改批单录入", httpMethod = "POST")
    @PostMapping(value = "/updateOfflineEndorse", produces = {MediaType.APPLICATION_JSON_UTF8_VALUE})
    public ResponseEntity updateOfflineEndorse(@RequestBody OfflineEndorse offlineEndorse) throws Exception {
        if (offlineEndorseService.updateOfflineEndorse(offlineEndorse) > 0) {
            return GenericDataResponse.ok();
        }
        return GenericDataResponse.errorWithMsg("没有修改记录!");
    }

    /**
     * 审核批单
     *
     * @return
     */
    @ApiOperation(value = "审核批单", notes = "审核批单", httpMethod = "POST")
    @PostMapping(value = "/auditOfflineEndorse", produces = {MediaType.APPLICATION_JSON_UTF8_VALUE})
    @AvoidRepeatableCommit
    public ResponseEntity auditOfflineEndorse(@RequestBody OfflineEndorse offlineEndorse) {
        if (null == offlineEndorse || null == offlineEndorse.getId()
                || null == offlineEndorse.getAuditStatus()) {
            return GenericDataResponse.errorWithMsg("批单信息/审核状态不能为空!");
        }
        String findCode = AUDIT_OFFLINE_ENDORSE + offlineEndorse.getId() + "_" + System.currentTimeMillis();
        //与审核同用一个key
        String redisKey = AUDIT_OFFLINE_ENDORSE + offlineEndorse.getId();
        if (!RedisUtil.setOneHoursLock(redisKey)) {
            return GenericDataResponse.errorWithMsg("批单信息/审核请求处理中，请稍等!");
        }
        try {
            return offlineEndorseService.auditOfflineEndorse(findCode, offlineEndorse);
        } catch (Exception e) {
            return GenericDataResponse.errorWithMsg(e.getMessage());
        } finally {
            //删除缓存
            RedisUtil.delete(redisKey);
            log.info("{}批单信息/审核任务结束!", findCode);
        }
    }


    /**
     * 推送未成功推送的批单信息
     *
     * @return
     */
    @ApiOperation(value = "推送未成功推送的批单信息", notes = "推送定单下未成功推送的保单到投保中心", httpMethod = "POST")
    @PostMapping(value = "/pushEndorseToPol/{id}", produces = {MediaType.APPLICATION_JSON_UTF8_VALUE})
    public ResponseEntity pushEndorseToPol(@ApiParam(value = "批单录入批次号", required = true) @PathVariable Long id) {
        if (null == id) {
            return GenericDataResponse.errorWithMsg("批单录入批次号不能为空!");
        }
        String findCode = "pushEndorseToPol_" + id + "_" + System.currentTimeMillis();
        //与审核同用一个key
        String redisKey = AUDIT_OFFLINE_ENDORSE + id;
        if (!RedisUtil.setOneHoursLock(redisKey)) {
            return GenericDataResponse.errorWithMsg("批单信息/审核请求处理中，请稍等!");
        }
        try {
            offlineEndorseService.pushEndorseToPol(findCode, id);
        } catch (Exception e) {
            return GenericDataResponse.errorWithMsg(e.getMessage());
        } finally {
            //删除缓存
            RedisUtil.delete(redisKey);
            log.info("{}批单信息/审核任务结束!", findCode);
        }
        return GenericDataResponse.ok();
    }

    /**
     * 通过保单号查询线下录入保单信息
     *
     * @return
     */
    @ApiOperation(value = "通过保单号查询线下录入保单信息", notes = "通过保单号查询线下录入保单信息", httpMethod = "POST")
    @PostMapping(value = "/queryPolicyByPolicyNo/{policyNo}", produces = {MediaType.APPLICATION_JSON_UTF8_VALUE})
    public ResponseEntity<GenericDataResponse<OfflineEndorsePolicyVo>> queryPolicyByPolicyNo(@ApiParam(value = "保单号", required = true) @PathVariable String policyNo) {
        try {
            OfflineEndorsePolicyVo offlineEndorsePolicyVo = offlineEndorseService.queryPolicyByPolicyNo(policyNo);
            return GenericDataResponse.okWithData(offlineEndorsePolicyVo);
        } catch (Exception e) {
            return GenericDataResponse.errorWithMsg(e.getMessage(), OfflineEndorsePolicyVo.class);
        }
    }

    @ApiOperation(value = "导出线下批单列表", notes = "统计结果并下载")
    @GetMapping(value = "/downList", produces = {MediaType.APPLICATION_JSON_UTF8_VALUE})
    public void downList(OfflineEndorseQO offlineEndorseQO, HttpServletResponse response, HttpServletRequest request) {
        String findCode = "EDU_" + System.currentTimeMillis();

        String userCode = request.getHeader(JTPF_USER_ID);
        String branchCodes = userService.getBranchCodes(findCode, userCode);
        offlineEndorseQO.setOperatorBranchCode(branchCodes);
        OutputStream os = null;
        try {
            //查询导出配置
            ExportConfigEntity exportConfigEntity = exportConfigService.getExportConfig(ExportChannelTypeEnum.OFFLINE_ENDORSE.getCode());
            if (null == exportConfigEntity) {
                return;
            }
            String fileName = exportConfigEntity.getFileName();

            os = response.getOutputStream();
            CsvExportUtil.responseSetProperties(fileName, response);
            //模板位置
            String titles = exportConfigEntity.getTitles();
            CsvExportUtil.setTitles(titles, os);
            List<OfflineEndorse> appList;
            int pn = 1;
            offlineEndorseQO.setPn(pn);
            offlineEndorseQO.setPs(CsvExportUtil.MAX_PAGE_SIZE);
            String[] keyArr = exportConfigEntity.getKeyArr().split(",");

            //分批查询并生成数据插入到导出文件中
            while (CollectionUtils.isNotEmpty(appList = offlineEndorseService.queryOfflineEndorse(offlineEndorseQO).getBody().getList())) {
                List list = Lists.transform(appList, (Function<OfflineEndorse, Object>) offlineEndorse -> new OfflineEndorseOutputDTO(offlineEndorse));
                CsvExportUtil.doExport(list, keyArr, os);
                offlineEndorseQO.setPn(++pn);
                if (offlineEndorseQO.getPs() > appList.size()) {
                    break;
                }
            }
        } catch (Exception e) {
            log.error("{}导出{}发生错误:", findCode, e);
        } finally {
            if (os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                }
            }
        }
    }

    /**
     * 删除订单
     *
     * @return
     */
    @ApiOperation(value = "删除批单", notes = "删除批单", httpMethod = "GET")
    @GetMapping(value = "/deleteEndorse/{id}", produces = {MediaType.APPLICATION_JSON_UTF8_VALUE})
    public ResponseEntity deleteEndorse(@ApiParam(value = "线下录单定单ID", required = true) @PathVariable Long id) {
        if (null == id) {
            return GenericDataResponse.errorWithMsg("保单号不能为空!");
        }
        return offlineEndorseService.deleteEndorse(id);
    }

}
